#ifndef numuCCPXSelection_h
#define numuCCPXSelection_h

#include "SelectionBase.hxx"
#include "Parameters.hxx"

//TODO: has to be changed later t nd280Samples::kFGD1NuMuCCPX
const nd280Samples::SampleEnum gkSampleEnumCCPX = nd280Samples::kFGD1NuMuCCQE;

class numuCCPXSelection: public SelectionBase{
 public:
  numuCCPXSelection(bool forceBreak=true);
  virtual ~numuCCPXSelection(){}

  //---- These are mandatory functions
  void DefineSteps();
  inline AnaBoxB* MakeBox();
  bool FillEventSummary(const AnaBoxB& box, AnaEventB& event, Int_t allCutsPassed[]);

  nd280Samples::SampleEnum GetSampleEnum(){return gkSampleEnumCCPX;}
};

class AnaBoxCCPX: public AnaBoxB{

public:
  enum eventtype{
    kZero = 0,
    kPionPlus=1,
    kPionMinus=2,
    kProton = 3,
    kOther = 4,
    kHasParent = 5,

    kMPion = 6,
    kMProton = 7,
    k0Muon = 8,
    k0Proton = 9,
    kMMuon = 10,
    kBad = 11
  };

  AnaBoxCCPX() {
    MuonCandidate = 0x0;
    ProtonCandidate = 0x0;

    XCandidate = 0x0;
    XPID = -999;
    //0 if ntrk=2, +1/-1 for ntrk=3
    XCharge = -999;

    NECalTracks = -999;
    ECalPDGSim = -999;

    EventTypeSim = -999;
    SimOtherPDG = -999;
  }  
  virtual ~AnaBoxCCPX(){}

  std::vector<AnaTrackB*> TrackerTracks;

  AnaTrackB* MuonCandidate;
  AnaTrackB* ProtonCandidate;

  AnaTrackB* XCandidate;
  Int_t XPID;
  Int_t XCharge; 

  Int_t NECalTracks;
  Int_t ECalPDGSim;

  Int_t EventTypeSim;
  Int_t SimOtherPDG;
};

inline AnaBoxB* numuCCPXSelection::MakeBox() {return new AnaBoxCCPX();}

namespace std_numuccPX_actions{
  void FindTracksWithTPC(const AnaEventB& event, AnaBoxCCPX& box);
  void FindTracksWithFGDAndNoTPC(const AnaEventB& event, AnaBoxCCPX& box);
  void FindECalActivity(const AnaEventB& event, AnaBoxB& box);
  void FindTrueCandidate(AnaBoxB& box);
}

namespace std_numuccPX_cuts{
  enum pid{
    kMuon=0,
    kProton=1,
    kPion=2,
    kElectron=3,
    kOther=4
  };
  
  Bool_t IsProton(AnaTrackB * trk);
  Bool_t IsPion(AnaTrackB * trk);
  Int_t GetPID(AnaTrackB * trk);
}

class MichelElectronCut: public StepBase{
 public:
  using StepBase::Apply;
  bool Apply(const AnaEventB& event, AnaBoxB& box) const;
  StepBase* MakeClone(){return new MichelElectronCut();}
};

class TrackChargeCut: public StepBase{
 public:
  using StepBase::Apply;
  bool Apply(const AnaEventB& event, AnaBoxB& box) const;
  StepBase* MakeClone(){return new TrackChargeCut();}
};


class FindMichelElectronsAction: public StepBase{
 public:
  using StepBase::Apply;
  bool Apply(const AnaEventB& event, AnaBoxB& box) const;
  StepBase* MakeClone(){return new FindMichelElectronsAction();}
};

class FindTrackerTracksAction: public StepBase{
 public:
  using StepBase::Apply;
  bool Apply(const AnaEventB& event, AnaBoxB& box) const;
  StepBase* MakeClone(){return new FindTrackerTracksAction();}
};

/// Find Muon and Proton candidates for all topologies
class FindCandidatesCut: public StepBase{
 public:
  using StepBase::Apply;
  bool Apply(const AnaEventB& event, AnaBoxB& box) const;
  StepBase* MakeClone(){return new FindCandidatesCut();}
};


//fine to use CCQE Vertex cut
class CommonVertexCut: public StepBase{
public:
  using StepBase::Apply;
  bool Apply(const AnaEventB& event, AnaBoxB& box) const;
  StepBase* MakeClone(){return new CommonVertexCut();}

  static int _cutX(){ return ND::params().GetParameterI("psycheSelections.numuCCQE.CutX1"); }
  static int _cutY(){ return ND::params().GetParameterI("psycheSelections.numuCCQE.CutY1"); }
  static int _cutZ(){ return ND::params().GetParameterI("psycheSelections.numuCCQE.CutZ1"); }
};


#endif
